package com.tianyu.inspection.common.component;

import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import com.tianyu.inspection.entity.*;
import com.tianyu.inspection.entity.model.QueryMo;
import com.tianyu.inspection.mapper.UserMapper;
import com.tianyu.inspection.service.api.IDangerProcessService;
import com.tianyu.inspection.service.api.IDangerService;
import com.tianyu.inspection.service.api.IFlyTaskService;
import com.tianyu.inspection.entity.*;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.ui.ModelMap;

import javax.annotation.Resource;
import java.io.*;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**********************************
 * @Author YSW
 * @Description
 * @Date 2021/2/19 - 09:36
 **********************************/

@Service
public class PdfModel {

    @Resource
    private IFlyTaskService flyTaskService;

    @Resource
    private IDangerService dangerService;

    @Resource
    private IDangerProcessService dangerProcessService;

    @Resource
    private UserMapper userMapper;

    @Resource
    private MapperModel mapperModel;

    private static BaseFont baseFont;
    private static Font font;
    private static final int LINE_HEIGHT = 24;

    static {
        try {
            URL resourceUrl = Thread.currentThread().getContextClassLoader().getResource("");
            if (Objects.nonNull(resourceUrl)) {
                URL url = PdfModel.class.getResource("");
                String protocol = url.getProtocol();
                if ("jar".equals(protocol)) {
                    baseFont = BaseFont.createFont(getFontPath(), BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
                } else if ("file".equals(protocol)) {
                    String fontPath = resourceUrl.getPath() + "font/SIMKAI.TTF";
                    baseFont = BaseFont.createFont(fontPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
                }
            }
            font = new Font(baseFont, 14);
        } catch (DocumentException | IOException e) {
            e.printStackTrace();
        }
    }

    private static String getFontPath() throws IOException {
        org.springframework.core.io.Resource resource = new ClassPathResource("classpath:font/SIMKAI.TTF");
        InputStream is = resource.getInputStream();
        String path = System.getProperty("user.dir") + "/resource/font";
        if (new File(path).mkdirs()) {
            FileOutputStream outputStream = new FileOutputStream(path + "/SIMKAI.TTF");
            byte[] buffer = new byte[1024];
            int length;
            while ((length = is.read(buffer)) != -1) {
                outputStream.write(buffer, 0, length);
            }
            is.close();
            outputStream.close();
        }
        return path + "/SIMKAI.TTF";
    }

    public static void main(String[] args) {
        try {
            ByteArrayOutputStream flayTaskReport = new PdfModel().createFlayTaskReport(1, 48);
            System.out.println(flayTaskReport.size());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public ByteArrayOutputStream createFlayTaskReport(int id, int projectId) throws Exception {
        QueryMo queryMo = new QueryMo();
        queryMo.put("id", id);
        queryMo.build(FlyTask.class, projectId);
        FlyTask flyTask = flyTaskService.selectOne(queryMo);
        if (Objects.isNull(flyTask)) {
            return null;
        }
        queryMo.remove("id");
        queryMo.setPageSize(-1);
        queryMo.put("flyTaskId", id);
        queryMo.build(Danger.class, projectId);
        IPage<Danger> dangerPage = dangerService.searchListPage(queryMo);
        //页面大小 595,842
        Rectangle rect = new Rectangle(PageSize.A4);
        //页面背景色
        rect.setBackgroundColor(new BaseColor(255, 255, 255));
        rect.setBorderWidth(150);
        rect.setBorderColor(new BaseColor(192, 80, 77));
        Document document = new Document(rect);
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        PdfWriter writer = PdfWriter.getInstance(document, outputStream);
        //PDF版本(默认1.4)
        writer.setPdfVersion(PdfWriter.PDF_VERSION_1_2);
        String taskNumber = flyTask.getTaskNumber();
        //文档属性
        document.addTitle("任务[" + taskNumber + "]飞行报告");
        document.addAuthor("Swyan");
        document.addSubject("飞行报告");
        document.addKeywords("飞行报告");
        document.addCreator("Swyan");
        //页边空白
        document.setMargins(20, 20, 50, 50);
        document.open();
        font = new Font(baseFont, 16);
        Paragraph paragraph = new Paragraph("任务[" + taskNumber + "]飞行报告\n", font);
        font = new Font(baseFont, 14);
        paragraph.setAlignment(Paragraph.ALIGN_CENTER);
        document.add(paragraph);
        //插入空行
        document.add(Chunk.NEWLINE);
        //插入表格1
        insertTable1(document, flyTask);
        document.add(Chunk.NEWLINE);
        //插入表格2
        insertTable2(document, flyTask);
        document.add(Chunk.NEWLINE);
        QueryMo queryMo1 = new QueryMo();
        queryMo1.put("flyTaskId", flyTask.getId());
        queryMo1.build(Danger.class, projectId);
        ModelMap modelMap = dangerService.dangerStatistics(queryMo1);
        //插入表格3
        insertTable3(document, modelMap);
        //插入表格4
        try {
            insertTable4(document, dangerPage.getRecords());
        } catch (Exception e) {
            e.printStackTrace();
        }
        //关闭文档
        document.close();
        return outputStream;
    }

    private void insertTable1(Document document, FlyTask flyTask) throws DocumentException {
        PdfPTable table = new PdfPTable(4);
        //设置表格具体宽度
        table.setWidthPercentage(80);
        table.setPaddingTop(30);
        table.getDefaultCell().setMinimumHeight(LINE_HEIGHT);
        table.getDefaultCell().setBorder(0);

        //设置每一列所占的长度
        table.setWidths(new float[]{30f, 30f, 30f, 35f});
        table.getDefaultCell().setHorizontalAlignment(PdfPCell.ALIGN_CENTER);

        table.addCell(new Phrase("飞行日期:", font));
        table.addCell(new Phrase(new SimpleDateFormat("yyyy-MM-dd").format(flyTask.getCreateTime()), font));

        table.addCell(new Phrase("执行飞机:", font));
        if (Objects.nonNull(flyTask.getUavId())) {
            table.addCell(new Phrase(flyTask.getUavName(), font));
        } else {
            table.addCell(new Phrase("未知", font));
        }

        table.addCell(new Phrase("飞手名称:", font));
        User user = userMapper.selectOne(new QueryWrapper<User>()
                .eq("id", flyTask.getUserId()).eq("project_id", flyTask.getProjectId()));
        if (Objects.nonNull(user)) {
            table.addCell(new Phrase(user.getNickName(), font));
        } else {
            table.addCell(new Phrase("未指定", font));
        }

        table.addCell(new Phrase("生成日期:", font));
        table.addCell(new Phrase(new SimpleDateFormat("yyyy-MM-dd").format(new Date()), font));
        document.add(table);
    }

    private void insertTable2(Document document, FlyTask flyTask) throws DocumentException {
        PdfPTable table = getPdfPTable(2);
        table.setPaddingTop(30);
        //设置每一列所占的长度
        table.setWidths(new float[]{30f, 70f});
        table.getDefaultCell().setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
        PdfPCell cell;
        cell = new PdfPCell();
        cell.setColspan(2);
        cell.setHorizontalAlignment(Element.ALIGN_CENTER);
        Paragraph paragraph = new Paragraph("任务名称: 未知", font);
        if (Objects.nonNull(flyTask.getTaskName())) {
            paragraph = new Paragraph("任务名称:" + flyTask.getTaskName(), font);
        }
        paragraph.setAlignment(1);
        cell.setMinimumHeight(LINE_HEIGHT);
        cell.setPhrase(paragraph);
        cell.setBackgroundColor(new BaseColor(235, 214, 214));
        cell.setBorderColor(new BaseColor(192, 80, 77));
        table.addCell(cell);
        table.addCell(new Paragraph("计划编号", font));
        if (Objects.nonNull(flyTask.getTaskNumber())) {
            table.addCell(new Phrase(flyTask.getTaskNumber(), font));
        } else {
            table.addCell(new Phrase("未知", font));
        }
        table.addCell(new Phrase("飞行时间", font));
        table.addCell(new Phrase(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(flyTask.getCreateTime()), font));
        table.addCell(new Phrase("飞行里程", font));
        table.addCell(new Phrase(flyTask.getFlightDistance() / 1000 + "(千米)", font));
        table.addCell(new Phrase("飞行时长", font));
        table.addCell(new Phrase(flyTask.getFlightDuration() / 60 + "(分钟)", font));
        table.addCell(new Phrase("观测方式", font));
        table.addCell(new Phrase("正射向下", font));
        table.addCell(new Phrase("是否有遥测", font));
        table.addCell(new Phrase(flyTask.getTelemetryUrl() == null ? "否" : "是", font));
        table.addCell(new Phrase("是否有视频", font));
        table.addCell(new Phrase(flyTask.getVideoUrl() == null ? "否" : "是", font));
        document.add(table);
    }

    private void insertTable3(Document document, ModelMap modelMap) throws DocumentException {
        PdfPTable table = getPdfPTable(4);
        PdfPCell cell;
        cell = new PdfPCell(new Phrase("险情统计", font));
        cell.setColspan(4);
        cell.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell.setMinimumHeight(LINE_HEIGHT);
        cell.setBackgroundColor(new BaseColor(235, 214, 214));
        cell.setBorderColor(new BaseColor(192, 80, 77));
        table.addCell(cell);
        cell = new PdfPCell(new Phrase("险情数量", font));
        setRowspanCell(table, cell);
        cell = new PdfPCell(new Phrase(modelMap.get("total").toString(), font));
        setRowspanCell(table, cell);
        final JSONObject jsonObject = new ObjectMapper().convertValue(modelMap.get("state"), JSONObject.class);
        jsonObject.forEach((k,v)->{
            table.addCell(new Phrase(k, font));
            table.addCell(new Phrase(v.toString(), font));
        });
        table.addCell(new Phrase("险情分布", font));
        cell = new PdfPCell();
        cell.setColspan(3);
        cell.setHorizontalAlignment(Element.ALIGN_CENTER);
        StringBuilder stringBuffer = new StringBuilder();
        final JSONObject jsonObject0 = new ObjectMapper().convertValue(modelMap.get("type"), JSONObject.class);
        jsonObject0.forEach((k,v)-> {
            if (!v.equals(0)){
                stringBuffer.append(k).append("[").append(v.toString()).append("] ");
            }
        });
        setParagraph(table, cell, new Paragraph(stringBuffer.toString(), font));
        document.add(table);
    }

    private void insertTable4(Document document, List<Danger> dangerList) throws DocumentException, IOException {
        for (Danger danger : dangerList) {
            document.add(Chunk.NEWLINE);
            QueryMo queryMo = new QueryMo();
            queryMo.setPageSize(-1);
            queryMo.put("dangerId", danger.getId());
            queryMo.build(DangerProcess.class, danger.getProjectId());
            List<DangerProcess> dangerProcessList = dangerProcessService.selectDangerProcessAndInspectorList(queryMo);
            PdfPTable table = getPdfPTable(4);
            PdfPCell cell;
            cell = new PdfPCell();
            cell.setColspan(4);
            cell.setHorizontalAlignment(Element.ALIGN_CENTER);
            Paragraph paragraph = new Paragraph("险情[" + danger.getId() + "]", font);
            paragraph.setAlignment(Paragraph.ALIGN_CENTER);
            cell.setMinimumHeight(LINE_HEIGHT);
            cell.setPhrase(paragraph);
            cell.setBackgroundColor(new BaseColor(235, 214, 214));
            cell.setBorderColor(new BaseColor(192, 80, 77));
            table.addCell(cell);
            table.addCell(new Phrase("详情类型", font));
            Integer typeId = danger.getDangerTypeId();
            final Map<Integer, DangerType> dangerTypeMap = mapperModel.getDangerTypeMap();
            final String type = dangerTypeMap.get(typeId).getTypeName();
            table.addCell(new Phrase(type, font));
            table.addCell(new Phrase("发现时间", font));
            table.addCell(new Phrase(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(danger.getCreateTime()), font));
            table.addCell(new Phrase("险情坐标", font));
            cell = new PdfPCell();
            cell.setColspan(3);
            cell.setHorizontalAlignment(Element.ALIGN_CENTER);
            paragraph = new Paragraph(danger.getLng() + "," + danger.getLat(), font);
            setParagraph(table, cell, paragraph);
            table.addCell(new Phrase("险情备注", font));
            cell = new PdfPCell();
            cell.setColspan(3);
            cell.setHorizontalAlignment(Element.ALIGN_CENTER);
            if (Objects.nonNull(danger.getRemarks())) {
                paragraph = new Paragraph(danger.getRemarks(), font);
            } else {
                paragraph = new Paragraph("无", font);
            }
            setParagraph(table, cell, paragraph);
            Image image = Image.getInstance(danger.getLabelImage());
            cell = new PdfPCell(new Phrase("险情图片", font));
            setCell(table, cell, image);
            cell = new PdfPCell(image, true);
            setColspanCell(table, cell);
            if (danger.getStatus() == 0) {
                table.addCell(new Phrase("责任人", font));
                PdfPCell cell1 = new PdfPCell();
                cell1.setColspan(3);
                cell1.setHorizontalAlignment(Element.ALIGN_CENTER);
                Paragraph paragraph1 = new Paragraph("未指定", font);
                setParagraph(table, cell1, paragraph1);
            } else {
                for (DangerProcess dangerProcess : dangerProcessList) {
                    table.addCell(new Phrase("责任人", font));
                    table.addCell(new Phrase(dangerProcess.getInspectorName(), font));
                    table.addCell(new Phrase("联系方式", font));
                    table.addCell(new Phrase(dangerProcess.getInspectorPhone(), font));

                    table.addCell(new Phrase("处理结果", font));
                    PdfPCell cell1 = new PdfPCell();
                    cell1.setColspan(3);
                    cell1.setHorizontalAlignment(Element.ALIGN_CENTER);

                    Paragraph paragraph1 = new Paragraph(dangerProcess.getStatus() == 2 ? "已完成" : "处理中", font);
                    setParagraph(table, cell1, paragraph1);
                    final String sceneImage = dangerProcess.getSceneImage();
                    if (Objects.nonNull(sceneImage)){
                        Image image1 = Image.getInstance(dangerProcess.getSceneImage());
                        cell1 = new PdfPCell(new Phrase("取证信息", font));
                        setCell(table, cell1, image1);

                        cell1 = new PdfPCell(new PdfPCell(image1, true));
                        setColspanCell(table, cell1);
                    }
                }
            }
            document.add(table);
        }
    }

    private static PdfPTable getPdfPTable(int columns) {
        PdfPTable table = new PdfPTable(columns);
        //设置表格具体宽度
        table.setWidthPercentage(90);
        table.getDefaultCell().setMinimumHeight(LINE_HEIGHT);
        table.getDefaultCell().setBackgroundColor(new BaseColor(244, 233, 233));
        table.getDefaultCell().setBorderColor(new BaseColor(192, 80, 77));
        table.getDefaultCell().setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
        return table;
    }

    private static void setRowspanCell(PdfPTable table, PdfPCell cell) {
        cell.setRowspan(3);
        cell.setBackgroundColor(new BaseColor(244, 233, 233));
        cell.setBorderColor(new BaseColor(192, 80, 77));
        cell.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell.setVerticalAlignment(PdfPCell.ALIGN_CENTER);
        cell.setPaddingTop(LINE_HEIGHT);
        table.addCell(cell);
    }

    private static void setColspanCell(PdfPTable table, PdfPCell cell) {
        cell.setColspan(3);
        cell.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell.setMinimumHeight(LINE_HEIGHT);
        cell.setBackgroundColor(new BaseColor(244, 233, 233));
        cell.setBorderColor(new BaseColor(192, 80, 77));
        cell.setPadding(0.5F);
        table.addCell(cell);
    }

    private static void setParagraph(PdfPTable table, PdfPCell cell, Paragraph paragraph) {
        paragraph.setAlignment(Paragraph.ALIGN_CENTER);
        cell.setMinimumHeight(LINE_HEIGHT);
        cell.setPhrase(paragraph);
        cell.setBackgroundColor(new BaseColor(244, 233, 233));
        cell.setBorderColor(new BaseColor(192, 80, 77));
        table.addCell(cell);
    }

    private static void setCell(PdfPTable table, PdfPCell cell, Image image) {
        cell.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell.setMinimumHeight(LINE_HEIGHT);
        cell.setBackgroundColor(new BaseColor(244, 233, 233));
        cell.setBorderColor(new BaseColor(192, 80, 77));
        cell.setPaddingTop((float) ((595 * 0.9 * 0.75 / image.getWidth() * image.getHeight()) - LINE_HEIGHT) / 2);
        table.addCell(cell);
    }
}
